using System.Collections.Generic;
using Config;
using Cysharp.Threading.Tasks;
using Data;
using Data.Bag;
using Data.Interface;
using Data.MapObject;
using Entity;
using GameTime;
using MoonFramework;
using MoonFramework.Scripts.Tool.DataSaveManager;
using MoonFramework.Scripts.Tool.System.Setting;
using MoonFramework.Template;
using MoonFramework.Test;
using Tool.Name;
using UnityEngine;

namespace Tool
{
    public class ArchiveManager : BaseManager<ArchiveManager>
    {
        public ArchiveManager()
        {
            LoadSavaData();
        }
        
        public EntityData EntityData { get; private set; }
        public ToolBarData ToolBarData { get; private set; }
        public MapInitData MapInitData { get; private set; }
        public MapData MapData { get; private set; } = new();
        public TimeData TimeData { get; private set; }
        public PlayerData PlayerData { get; private set; }
        public ScienceData ScienceData { get; private set; }

        private readonly EntityPro EntityDataPro = new();
        private readonly ToolBarDataPro ToolBarDataPro = new();
        private readonly MapInitDataPro MapInitDataPro = new();
        private readonly MapDataPro MapDataPro = new();
        private readonly TimeDataPro TimeDataPro = new();
        private readonly PlayerDataPro PlayerDataPro = new();
        private readonly ScienceDataPro ScienceDataPro = new();
        private readonly MapBlockDataPro MapBlockDataPro = new();
        public bool HasArchive;

        #region 保存

        private void LoadSavaData()
        {
            // 加载存档的基础数据
            var saveItem = SaveManager.GetSaveItem(0);
            HasArchive = saveItem != null;
        }

        public void CreateNewArchive(int mapSize, int mapSeed, int spawnSeed, float marshLimit)
        {
            // 清空当前存档并创建新存档
            SaveManager.DeleteSaveItem(0);
            SaveManager.CreateSaveItem();
            HasArchive = true;

            // 设置新存档数据

            #region 地图

            var mapConfig = ConfigManager.Instance.GetConfig<MapConfig>(ConfigName.Map, 0);
            float mapSizeOnWorld = mapSize * mapConfig.mapBlockSize;
            MapInitData = new MapInitData
            {
                mapSize = mapSize,
                mapSeed = mapSeed,
                spawnSeed = spawnSeed,
                marshLimit = marshLimit
            };
            MapData = new MapData
            {
                CurID = 1,
                MapBlocks = new List<Vector2Int>(),
                MapObjectTypeData = new Dictionary<ulong, IMapObjectTypeData>()
            };

            #endregion

            #region 角色

            //物品
            EntityData = new EntityData
            {
                Name = "Player",
                position = new Vector3(mapSizeOnWorld / 2, 0, mapSizeOnWorld / 2),
                rotation = Vector3.zero
            };

            //玩家
            var playerConfig = ConfigManager.Instance.GetConfig<PlayerConfig>(ConfigName.Player, 0);
            PlayerData = new PlayerData
            {
                Hp = playerConfig.MaxHp,
                Hunger = playerConfig.MaxHunger
            };

            #endregion

            #region 背包

            //写死14个
            ToolBarData = new ToolBarData(14);

            // #region 测试数据
            //
            ToolBarData.ItemDataList[0] = ItemData.CreateItemData(1);
            ToolBarData.ItemDataList[1] = ItemData.CreateItemData(10);
            ToolBarData.ItemDataList[2] = ItemData.CreateItemData(9);
            //
            // #endregion
            
            #endregion

            #region 时间

            var timeConfig = ConfigManager.Instance.GetConfig<TimeConfig>(ConfigName.Time, 0);
            TimeData = new TimeData
            {
                curState = nameof(MorningTime),
                curTime = timeConfig.timeDatas[0].durationTime,
                curDay = 0
            };

            #endregion

            #region 科技

            ScienceData = new ScienceData();

            #endregion

            // 保存数据
            SaveAllData(0);
        }

        private void SaveAllData(int curID)
        {
            // 集中保存数据
            SaveEntityData(curID);
            SaveMapData(curID);
            SaveToolBarData(curID);
            SaveTimeData(curID);
            SavePlayerData(curID);
            SaveScienceData(curID);
        }

        /// <summary>
        ///     保存科技数据
        /// </summary>
        public void SaveScienceData(int curID)
        {
            var scienceDataPro = new ScienceDataPro();
            foreach (var id in ScienceData.UnlockScienceSet)
                scienceDataPro.UnlockScienceSet.Add(id);
            scienceDataPro.SaveObject(curID);
        }

        public void SavePlayerData(int curID)
        {
            PlayerDataPro.Hp = PlayerData.Hp;
            PlayerDataPro.Hunger = PlayerData.Hunger;
            PlayerDataPro.SaveObject(curID);
        }

        public void SaveEntityData(int curID)
        {
            EntityDataPro.Name = "Player";
            EntityDataPro.NowTime = 0f;
            EntityDataPro.Position = new Vector3Pro
                { X = EntityData.position.x, Y = EntityData.position.y, Z = EntityData.position.z };
            EntityDataPro.Rotation = new Vector3Pro
                { X = EntityData.rotation.x, Y = EntityData.rotation.y, Z = EntityData.rotation.z };
            EntityDataPro.SaveObject(curID);
        }

        public void SaveMapData(int curID)
        {
            MapInitDataPro.MapSize = MapInitData.mapSize;
            MapInitDataPro.MapSeed = MapInitData.mapSeed;
            MapInitDataPro.MarshLimit = MapInitData.marshLimit;
            MapInitDataPro.SaveObject(curID);
            MapDataPro.CurID = MapData.CurID;
            MapDataPro.SaveObject(curID);
        }

        public void SaveToolBarData(int curID)
        {
            var weaponData = ToolBarData.WeaponSlotItemData?.ItemTypeData as ItemWeaponData;

            ToolBarDataPro.ItemDataList.Clear();
            ToolBarDataPro.WeaponItemData = weaponData != null
                ? new ItemDataPro
                {
                    ConfigID = ToolBarData?.WeaponSlotItemData?.ConfigID ?? 0, // 防止ToolBarData或WeaponItemData为null
                    WeaponData = new WeaponDataPro
                    {
                        Durability = weaponData.Durability
                    }
                }
                : null;

            // 确保ToolBarData和ItemDataList不为null
            if (ToolBarData?.ItemDataList != null)
                foreach (var t in ToolBarData.ItemDataList)
                {
                    ItemDataPro itemDataPro = new();
                    if (t != null)
                    {
                        itemDataPro.ConfigID = t.ConfigID;
                        switch (t.ItemTypeData)
                        {
                            case ItemConsumableItemData itemConsumableData:
                                itemDataPro.ConsumableData = new ConsumableDataPro
                                {
                                    Count = itemConsumableData.Count
                                };
                                break;
                            case ItemMaterialItemData itemMaterialData:
                                itemDataPro.MaterialData = new MaterialDataPro
                                {
                                    Count = itemMaterialData.Count
                                };
                                break;
                        }
                    }

                    ToolBarDataPro.ItemDataList.Add(itemDataPro);
                }

            ToolBarDataPro.SaveObject(curID);
        }

        public void SaveTimeData(int curID)
        {
            TimeDataPro.CurState = TimeData.curState;
            TimeDataPro.CurTime = TimeData.curTime;
            TimeDataPro.CurDay = TimeData.curDay;
            TimeDataPro.SaveObject(curID);
        }

        public void SavaBlockData(Vector2Int index, MapBlockData mapBlockData)
        {
            MapBlockDataPro.MapBlockObjects.Clear();
            foreach (var block in mapBlockData.MapBlockMapObjects)
                MapBlockDataPro.MapBlockObjects.Add(new MapObjectDataPro
                {
                    ID = block.Key,
                    ConfigID = block.Value.configID,
                    Position = new Vector3Pro
                        { X = block.Value.position.x, Y = block.Value.position.y, Z = block.Value.position.z }
                });
            SaveManager.SaveObject(MapBlockDataPro, $"Map_{index}");
        }

        #endregion

        #region 加载数据

        //为什么加载选择new，因为这里的数据只会在游戏开始时加载一次，不会在游戏中修改，防止数据污染
        public async UniTaskVoid LoadCurArchive()
        {
            // 异步并行加载存档数据
            var mapInitTask = SaveManager.LoadObjectAsync<MapInitDataPro>();
            var entityTask = SaveManager.LoadObjectAsync<EntityPro>();
            var toolBarDataTask = SaveManager.LoadObjectAsync<ToolBarDataPro>();
            var timeDataTask = SaveManager.LoadObjectAsync<TimeDataPro>();
            var playerDataTask = SaveManager.LoadObjectAsync<PlayerDataPro>();
            var mapDataTask = SaveManager.LoadObjectAsync<MapDataPro>();
            var scienceDataTask = SaveManager.LoadObjectAsync<ScienceDataPro>();
            HandleEntityData(await entityTask);
            HandleMapInitData(await mapInitTask);
            HandleToolBarData(await toolBarDataTask);
            HandleTimeData(await timeDataTask);
            HandlePlayerData(await playerDataTask);
            HandleMapData(await mapDataTask);
            HandleScienceData(await scienceDataTask);
        }

        private void HandleScienceData(ScienceDataPro scienceDataTask)
        {
            ScienceData = new ScienceData();
            foreach (var id in scienceDataTask.UnlockScienceSet)
                ScienceData.UnlockScienceSet.Add(id);
        }

        private void HandleMapData(MapDataPro mapDataTask)
        {
        }

        private void HandlePlayerData(PlayerDataPro playerDataPro)
        {
            PlayerData = new PlayerData
            {
                Hp = playerDataPro.Hp,
                Hunger = playerDataPro.Hunger
            };
        }

        private void HandleTimeData(TimeDataPro timeDataPro)
        {
            TimeData = new TimeData(timeDataPro);
        }

        public async UniTask<MapBlockData> LoadMapBlock(Vector2Int index)
        {
            // 异步加载地图块数据
            var mapBlockData = new MapBlockData { MapBlockMapObjects = new Dictionary<ulong, MapObjectData>() };
            var mapBlockDataPro = await SaveManager.LoadObjectAsync<MapBlockDataPro>($"Map_{index}");
            HandleMapBlockData(mapBlockDataPro, mapBlockData);
            return mapBlockData;
        }

        private void HandleToolBarData(ToolBarDataPro bagDataPro)
        {
            ToolBarData = new ToolBarData();
            ToolBarData.Init(bagDataPro);
        }

        private void HandleMapInitData(MapInitDataPro mapInitDataPro)
        {
            MapInitData = new MapInitData(mapInitDataPro);
        }

        private void HandleEntityData(EntityPro entityPro)
        {
            EntityData = new EntityData(entityPro);
        }

        private void HandleMapBlockData(MapBlockDataPro mapBlockDataPro, MapBlockData mapBlockData)
        {
            foreach (var block in mapBlockDataPro.MapBlockObjects)
            {
                var mapBlockObjectData = MapObjectData.CreateMapObjectData(0, block.ConfigID, -1,
                    new Vector3(block.Position.X, block.Position.Y, block.Position.Z));
                mapBlockData.MapBlockMapObjects.Add(block.ID, mapBlockObjectData);
            }
        }

        #endregion

        #region 对象字典操作
        /// <summary>
        ///     获取地图对象的类型数据
        /// </summary>
        public IMapObjectTypeData GetIMapObjectTypeData(ulong id)
        {
            return MapData.MapObjectTypeData[id];
        }

        public bool TryGetIMapObjectTypeData(ulong id, out IMapObjectTypeData mapObjectTypeData)
        {
            return MapData.MapObjectTypeData.TryGetValue(id, out mapObjectTypeData);
        }

        /// <summary>
        ///     添加地图对象的类型数据
        /// </summary>
        public void AddIMapObjectTypeData(ulong mapObjectID, IMapObjectTypeData mapObjectTypeData)
        {
            MapData.MapObjectTypeData.Add(mapObjectID, mapObjectTypeData);
        }

        /// <summary>
        ///     移除地图对象的类型数据
        /// </summary>
        public void RemoveIMapObjectTypeData(ulong mapObjectID)
        {
            MapData.MapObjectTypeData.Remove(mapObjectID);
        }
        #endregion

        /// <summary>
        /// 删除存档
        /// </summary>
        public void ClearArchive()
        {
            SaveManager.DeleteSaveItem(0);
            LoadSavaData();
        }
    }
}